#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

typedef  unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;

#define VENDOR_STORAGE_PATH "/dev/vendor_storage"
#define VENDOR_REQ_TAG 0x56524551
#define VENDOR_READ_IO _IOW('v',0X01,unsigned int)
#define VENDOR_WRITE_IO _IOW('v',0X02,unsigned int)

#define VENDOR_SN_ID 1
#define VENDOR_WIFI_MAC_ID 2
#define VENDOR_LAN_MAC_ID 3
#define VENDOR_BLUETOOTH_ID 4

#define OP_R 0
#define OP_W 1

struct rk_vendor_req {
	u32 tag;
	u16 id;
	u16 len;
	u8 data[1];
};


/**
 * 以16进制的形式输出指定的内容
 * @param msg [内容]
 * @param len [内容长度]
 */
char* hex_dump(const char *msg, int len)
{
	#define BSIZE 1024
	static char buf[BSIZE];
	int n = 0, i=0;
	for(i=0; i<len; i++){
		n +=snprintf(buf+n, BSIZE, "%02x", msg[i]);
	}
	buf[n] = 0;
	return buf;
}

/**
 * 读取vendor_storage的内容并显示
 * @param  id  [ id值]
 * @param  hex [是否以16进制的方式显示]
 * @return     [0 成功， <0 失败]
 */
int vendor_storage_read_test(int id, int hex)
{
	int ret;
	u8 p_buf[2048];
	struct rk_vendor_req *req;
	memset(p_buf, 0, sizeof(p_buf));
	req = (struct rk_vendor_req *)p_buf;
	int sys_fd = open(VENDOR_STORAGE_PATH, O_RDWR, 0);
	if(sys_fd<0){
		printf("open %s failed, msg=%s\n", VENDOR_STORAGE_PATH, strerror(errno));
		return -1;
	}
	req->tag = VENDOR_REQ_TAG;
	req->id = id;
	req->len = 512;
	ret = ioctl(sys_fd, VENDOR_READ_IO, req);
	if(ret < 0){
		printf("read ID %d fail, ret=%d\n", id, ret);
	}else{
		printf("read ID %d ret=%d, len=%u, msg=%s\n", id, ret, req->len,
			hex ? hex_dump((char*)req->data, req->len) : (char *)req->data);
	}
	close(sys_fd);
	return ret;
}


/**
 * 写vendor_storage指定的ID
 * @param  id  [ID值]
 * @param  len [内容的长度]
 * @param  msg [内容地址]
 * @return     [description]
 */
int vendor_storage_write_test(int id, int len, char *msg)
{
	int ret;
	u8 p_buf[2048];
	struct rk_vendor_req *req;
	memset(p_buf, 0, sizeof(p_buf));
	req = (struct rk_vendor_req *)p_buf;
	int sys_fd = open(VENDOR_STORAGE_PATH, O_RDWR, 0);
	if(sys_fd<0){
		printf("open %s failed, msg=%s\n", VENDOR_STORAGE_PATH, strerror(errno));
		return -1;
	}
	req->tag = VENDOR_REQ_TAG;
	req->id = id;
	req->len = len;
	memcpy(req->data, msg, len);
	ret = ioctl(sys_fd, VENDOR_WRITE_IO, req);
	if(ret < 0){
		printf("write ID %d fail, ret=%d\n", id, ret);
	}
	close(sys_fd);
	return ret;
}


static void usage(const char *name)
{
	printf("Usage: %s [-r][-w xxx][-i n] [-x] [-h]\n", name);
	printf("Some predefined value are:\n");
	printf("1 VENDOR_SN_ID\n");
	printf("2 VENDOR_WIFI_MAC_ID\n");
	printf("3 VENDOR_LAN_MAC_ID\n");
	printf("4 VENDOR_BLUETOOTH_ID\n");
}

int main(int ac, char *av[])
{
	int opt;
	char buf[64];
	int rw = OP_R;
	int id = 1;
	int hex = 0;
	while ((opt = getopt(ac, av, "rw:i:xh")) != -1) {
		switch(opt) {
		case 'x':
			hex=1;
			break;
		case 'r':
			rw = OP_R;
			break;
		case 'w':
			rw = OP_W;
			strcpy(buf, optarg);
			break;
		case 'i':
			id = atoi(optarg);
			break;
		default:
			usage(av[0]);
			exit(EXIT_FAILURE);
			break;
		}
	}
	switch(rw){
	case OP_R:
		vendor_storage_read_test(id, hex);
		break;
	case OP_W:
		vendor_storage_write_test(id, strlen(buf), buf);
		vendor_storage_read_test(id, hex);
		break;
	default:
		printf("Unknow op: %d\n", rw);
		break;
	}
	return 0;
}

